﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

using zijian666.Core;
using zijian666.Http;

namespace UnitTest1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void UrlTest()
        {
            using var client = new HttpClient();
            var www = client.Fluent();


            var arr = new (string str, string format, string expected)[]
            {
                ("baidu.com","url","http://baidu.com/"),
                ("https://www.baidu.com","url","https://www.baidu.com/"),
                ("https://www.baidu.com/a/b/c?id=1#123","url","https://www.baidu.com/a/b/c?id=1#123"),
                ("https://www.baidu.com/a/b/c?id=1#123","Scheme","https"),
                ("https://www.baidu.com/a/b/c?id=1#123","HostAndPort","www.baidu.com:443"),
                ("https://www.baidu.com/a/b/c?id=1#123","Path,Query","/a/b/c?id=1"),
                ("https://www.baidu.com/a/b/c?id=1#123","Path,Fragment","/a/b/c#123"),
            };


            foreach (var (str, format, expected) in arr)
            {
                var url = www.Path(str).ToString(format);
                Assert.AreEqual(expected, url, $"{str} + {format} 测试失败");
            }

            foreach (var (str, format, expected) in arr)
            {
                var url = www.BaseUrl(str).ToString(format);
                Assert.AreEqual(expected, url, $"{str} + {format} 测试失败");
            }

            var arr2 = new (string str, string format, string expected)[]
            {
                ("/a/b/c?id=1#123","url","https://www.baidu.com/a/b/c?id=1#123"),
                ("/a/b/c?id=1#123","Scheme","https"),
                ("/a/b/c?id=1#123","HostAndPort","www.baidu.com:443"),
                ("/a/b/c?id=1#123","Path,Query","/a/b/c?id=1"),
                ("/a/b/c?id=1#123","Path,Fragment","/a/b/c#123"),
            };


            foreach (var (str, format, expected) in arr2)
            {
                var url = www.BaseUrl(new Uri("https://www.baidu.com")).Path(str).ToString(format);
                Assert.AreEqual(expected, url, $"{str} + {format} 测试失败");
            }




        }

        [TestMethod]
        public void KeyValuePraseTest()
        {

            var arr = new (object obj, string expected)[]
            {
                (null,""),
                (new { id = 1, name = "zijian666" },"id=1&name=zijian666"),
                ("zijian666","=zijian666"),
                (new object[]{ 1,"zijian666",new Guid("00000000-0000-0000-0000-000000001111")},"=1,zijian666,00000000-0000-0000-0000-000000001111"),
                (new Dictionary<string,object>{ ["id"]=1,["array"] = new int[]{ 1,2,3,4} }, "id=1&array=1,2,3,4"),
                (new { id = 1, name = "zijian666", prop = new Dictionary<string,object>{ ["id"] = 1,["array"] = new int[]{ 1,2,3,4} } }, "id=1&name=zijian666&prop.id=1&prop.array=1,2,3,4"),
            };


            foreach (var (obj, expected) in arr)
            {
                var x = KeyValuePraser.Enumerable(obj);
                var y = new FormUrlEncodedContent(x).ReadAsString();

                Assert.AreEqual(expected, Uri.UnescapeDataString(y));
            }



        }

        [TestMethod]
        public void PathTemplateTest()
        {
            var obj = new
            {
                id = 1,
                name = "zijian666",
                time = "2020-10-17 16:14:23",
                array = new[] { 1, 2, 3, 4, }
            };

            using var client = new HttpClient();
            var url = client.Fluent()
                .BaseUrl("baidu.com/a/b/c")
                .Path("user/{id}/name={name}/{array}/{time}", obj)
                .ToString("url");
            Assert.AreEqual("http://baidu.com/a/b/user/1/name=zijian666/1,2,3,4/2020-10-17%2016:14:23", url);
        }

        [TestMethod]
        public void JsonBodyTest()
        {
            var obj = new
            {
                id = 1,
                name = "zijian666",
                time = "2020-10-17 16:14:23",
                array = new[] { 1, 2, 3, 4, }
            };
            using var client = new HttpClient();
            var raw = client.Fluent()
               .BaseUrl("baidu.com")
               .Path("get/user")
               .AddDefaultHeaders()
               .JsonBody(obj)
               .ToString();

            Console.WriteLine(raw);
        }

        [TestMethod]
        public void UploadTest()
        {
            {
                var client = new HttpClient();
                var file = Directory.GetFiles("d:\\")
                    .Select(x => new FileInfo(x))
                    .First(x => x.Length > 10240 && x.Length < 100 * 1024);

                var fluent = client.Fluent()
                   .BaseUrl("https://baidu.com")
                   .Path("image/upload")
                   .AddDefaultHeaders()
                   .Form(
                        new FormData("name", "test.jpg"),
                        new FormData("bytes", new byte[] { 111, 222, 123 }, "ok.db")
                    //new FormData("file", file)
                    );

                //Console.WriteLine(fluent.ToString());
                var raw = fluent.Send(30000);

                Console.WriteLine(raw);
            }

            {
                HttpClientExtensions.SetSendSyncAction(1);
                var client = new HttpClient();
                var file = Directory.GetFiles("d:\\")
                    .Select(x => new FileInfo(x))
                    .First(x => x.Length > 10240 && x.Length < 100 * 1024);

                var fluent = client.Fluent()
                   .BaseUrl("https://baidu.com")
                   .Path("image/upload")
                   .AddDefaultHeaders()
                   .Form(
                        new FormData("name", "test.jpg"),
                        new FormData("bytes", new byte[] { 111, 222, 123 }, "ok.db")
                    //new FormData("file", file)
                    );

                var raw = fluent.Send(30000);

                Console.WriteLine(raw);

                HttpClientExtensions.SetSendSyncAction(0);
            }

        }

        [TestMethod]
        public async Task UploadTestAsnyc()
        {
            ServicePointManager.DefaultConnectionLimit = 256;
            var client = new HttpClient();
            var file = Directory.GetFiles("d:\\")
                .Select(x => new FileInfo(x))
                .First(x => x.Length > 10240 && x.Length < 100 * 1024);

            var fluent = client.Fluent()
               .BaseUrl("https://baidu.com")
               .Path("image/upload")
               .AddDefaultHeaders()
               .Form(
                    new FormData("name", "test.jpg"),
                    new FormData("bytes", new byte[] { 111, 222, 123 }, "ok.db")
                //new FormData("file", file)
                );

            var raw = await fluent.SendAsync(30000);

            Console.WriteLine(raw);


        }

        [TestMethod]
        public void DynamicTest()
        {
            using var http = new HttpClient();
            var s = http.Fluent()
                .BaseUrl("https://blqw-oss-web.oss-cn-hangzhou.aliyuncs.com/")
                .Path("test.json")
                .ReadAsDynamic();
            Console.WriteLine(s);
            Console.WriteLine($"code = {s.code}");
            Console.WriteLine($"message = {s.message}");
            Console.WriteLine($"success = {s.success}");
            Assert.AreEqual((int)s.code, 0);
            Assert.AreEqual((string)s.code, "0");
            Assert.AreEqual((string)s.message, "ok");
            Assert.AreEqual((string)s.success, "true");
            Assert.AreEqual((bool)s.success, true);
        }

        [TestMethod]
        public void GetRawTest()
        {
            using var client = new HttpClient();
            var raw = client.Fluent()
               .BaseUrl("https://baidu.com")
               .Path("get/user")
               .Header("abc", "111")
               .ToString();
            Assert.IsTrue(raw.Contains("abc: 111"));
        }
    }
}
